package com.watf.functions.core;

import java.io.File;
import java.io.IOException;

import org.openqa.selenium.io.FileHandler;
import org.testng.Reporter;
import com.thoughtworks.selenium.Selenium;


/*
 * FileName:BasicFuncs. Implements the Funcs interface.
 * This file is used to define the common function used in the testing. 
 * 
 * If you want to change the file, please update the info bellow after your updating.
 * 
 * Change History:
 * 2011-6-26 First Draft   Jester.
 */


public class DefaultBasicFuncs implements BasicFuncs {
	
	
	/*
	 * The link locator used in the system.
	 */
	String Next_LINK = "link=Next";
	String First_LINK = "link=1";
	public static final String DEFAULT_WAIT_TIME = "30000"; // default wait time for loading a page, added Bear
	
	public static final String JAVA_SCRIPT_DIR = DefaultConfigUtil.getConfigData( "Base_Path" ) + "Tools\\JavaScript\\";

	/**
	 * This method is designed to verify if the element can be found on the page
	 * which have many sub-pages.
	 * 
	 * Author:Jester
	 */
	public boolean findElementsOnTables(Selenium selenium, String ielement)
			throws Exception {		
		ielement=ielement.trim();

		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}


		while (selenium.isElementPresent(Next_LINK)) {
			try {
				if (selenium.isElementPresent(ielement)) {
					return true;
				}
				selenium.click(Next_LINK);
				selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
		}

		try {
			if (selenium.isElementPresent(ielement)) {
				return true;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}

	/**
	 * This method is designed to click the radio button if the element can be
	 * found on the page.
	 * 
	 * Author:Jester
	 */
	public boolean selectElementsOnTables(Selenium selenium, String ielement)
			throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/
		ielement=ielement.trim();
		
		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}

		
		while (selenium.isElementPresent(Next_LINK)) {
			try {
				if (selenium.isElementPresent(ielement)) {
					selenium.click(ielement);
					return true;
				}
				selenium.click(Next_LINK);
				selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
		}
	
		try {
			if (selenium.isElementPresent(ielement)) {
				selenium.click(ielement);
				return true;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}
	
	/**
	 * This Method is designed to check the radio button with no value
	 * specified.
	 * 
	 * But you must provided the table string and the name string.
	 * 
	 * Author:Jester
	 */
	public boolean selectRadioButtonFromTable(Selenium selenium, String iTable,
			String iName) throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/
		
		iTable=iTable.trim();
		iName=iName.trim();
		
		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
		
		while (selenium.isElementPresent(Next_LINK)) {
			try {
				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[2]"))
					{							
						if (selenium.getText(iTable + "//tr[" + i + "]//td[2]")
								.equals(iName)) {
							selenium.click(iTable + "//tr[" + i
									+ "]//td[1]/input");
							return true;
						}
					}
							
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
	
		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
				if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[2]"))
				{
					if (selenium.getText(iTable + "//tr[" + i + "]//td[2]")
							.equals(iName)) 
					{

							selenium.click(iTable + "//tr[" + i + "]//td[1]//input");	
						return true;
					}						
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}

	/**
	 * This Method is designed to check the radio button with no value
	 * specified.
	 * 
	 * But you must provided the table string and the name string and the TD
	 * number.
	 * 
	 * Author:Jester
	 */
	public boolean selectRadioButtonFromTable(Selenium selenium, String iTable,
			String iName, int iTd) throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/
		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
		
		iTable=iTable.trim();
		iName=iName.trim();
		
		while (selenium.isElementPresent(Next_LINK)) {
			try {
				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[" + iTd + "]"))
					{							
						if (selenium.getText(
								iTable + "//tr[" + i + "]//td[" + iTd + "]")
								.equals(iName)) {
							selenium.click(iTable + "//tr[" + i
									+ "]//td[1]/input");
							return true;
						}
					}
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
	
		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
				if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[" + iTd + "]"))
				{						
					if (selenium.getText(
							iTable + "//tr[" + i + "]//td[" + iTd + "]").equals(
									iName)) {
						selenium.click(iTable + "//tr[" + i + "]//td[1]/input");
						return true;
					}
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}
	
	/**
	 * Select Radio Button From Table For Remove Local Pairs
	 * 
	 * Author:Totti
	 */
	public boolean selectRadioButtonFromTable(Selenium selenium, String iTable,
			String iName1, String iName2) throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/
		
		iTable=iTable.trim();
		iName1=iName1.trim();
		iName2=iName2.trim();
		
		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}

		while (selenium.isElementPresent(Next_LINK)) {
			try {
				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.getText(iTable + "//tr[" + i + "]//td[2]")
							.trim().equals(iName1.trim())
							&& selenium
									.getText(
											iTable + "//tr[" + i + "]//td[3]")
									.trim().equals(iName2.trim())) {
						selenium.click(iTable + "//tr[" + i
								+ "]//td[1]//input");
						return true;
					}
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
	
		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "/tr[" + i + "]")) {
				if (selenium.getText(iTable + "//tr[" + i + "]//td[3]")
						.trim().equals(iName2.trim())) {
					selenium.click(iTable + "//tr[" + i + "]//td[1]//input");
					return true;
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}


	/**
	 * This Method is designed to check if the item presents in the table.
	 * 
	 * But you must provided the table string and the name string. Author:Jester
	 */
	public boolean isPresentInTable(Selenium selenium, String iTable,
			String iName) throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/

		iTable=iTable.trim();
		iName=iName.trim();
		
		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}

		
		while (selenium.isElementPresent(Next_LINK)) {
			try {
				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[2]"))
					{
						if (selenium.getText(iTable + "//tr[" + i + "]/td[2]").trim()
								.equals(iName)) {
							return true;
						}
					}
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
	
		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
				if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[2]"))
				{						
					if (selenium.getText(iTable + "//tr[" + i + "]//td[2]").trim()
							.equals(iName)) {
						return true;
					}
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}

	/**
	 * This Method is designed to check if the item presents in the table.
	 * 
	 * But you must provided the table string and the name string and the TD
	 * number. Author:Jester
	 */
	public boolean isPresentInTable(Selenium selenium, String iTable,
			String iName, int iTd) throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/
		
		iTable=iTable.trim();
		iName=iName.trim();

		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}

		while (selenium.isElementPresent(Next_LINK)) {
			try {
				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[" + iTd + "]"))
					{							
						if (selenium.getText(
								iTable + "//tr[" + i + "]//td[" + iTd + "]").trim()
								.equals(iName)) {
							return true;
						}
					}
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
	
		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
				if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td[" + iTd + "]"))
				{						
					if (selenium.getText(
							iTable + "//tr[" + i + "]//td[" + iTd + "]").trim().equals(
									iName)) {
						return true;
					}
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;

	}
	
	
	/**
	 * This Method is defined to check if all the names you provided can be found in the same row.
	 * Use the first name pair as the default key word. If any of the name pairs can't be found then return false.
	 * 
	 * You must provide the name pair one after one, and make sure the fields you want to check are exist in the same row.
	 * columnNumber1=value1,columnNumber2=value2
	 * For example: 1=abc,2=cdf,4=ecv
	 * 
	 * 
	 * Will use the first pair as the default key word to locate the row.
	 * if any value you provided can't be found in the table. The false will be returned.
	 * 
	 * 
	 * Author:Jester
	 */
	
	public boolean isAllPresentInTable(Selenium selenium, String iTable,
			String NamePairs) throws Exception {		

		iTable=iTable.trim();
		NamePairs=NamePairs.trim();
		
		String[] iNamePairs=NamePairs.split(",");
		String ikeyTd=iNamePairs[0].split("=")[0].trim();
		String ikeyName=iNamePairs[0].split("=")[1].trim();
		
		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}

		
		while (selenium.isElementPresent(Next_LINK)) {
			try {

				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td["+ikeyTd+"]"))
					{
						if (selenium.getText(iTable + "//tr[" + i + "]/td["+ikeyTd+"]").trim()
								.equals(ikeyName)) {
							for (int j=1;j<iNamePairs.length;j++)
							{			
								String[] iValue=iNamePairs[j].split("=");
								String iTd=iValue[0].trim();
								String iName=iValue[1].trim();
								
								if(selenium.getText(iTable+"//tr["+i+"]/td["+iTd+"]").trim().equals(iName))
								{
									continue;
								}
								else
								{
									Reporter.log("The contains in the "+iTd+" column is not equals the value you expected:"+iName);
									return false;
								}
							}
							return true;
						}
					}
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return false;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}
	
		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
				if (selenium.isElementPresent(iTable + "//tr[" + i + "]//td["+ikeyTd+"]"))
				{
					if (selenium.getText(iTable + "//tr[" + i + "]/td["+ikeyTd+"]").trim()
							.equals(ikeyName)) {
						for (int j=1;j<iNamePairs.length;j++)
						{			
							String[] iValue=iNamePairs[j].split("=");
							String iTd=iValue[0].trim();
							String iName=iValue[1].trim();
							
							if(selenium.getText(iTable+"//tr["+i+"]/td["+iTd+"]").trim().equals(iName))
							{
								continue;
							}
							else
							{
								Reporter.log("The contains in the "+iTd+" column is not equals the value you expected:"+iName);
								return false;
							}
						}
						return true;
					}
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return false;
		}
		
		return false;
	}

	/*
	 * 1. Find the row whose name equals iName, 2. Return the text in column iTd
	 * of this row. Author: Shenyang Create Time: 2011-6-22
	 */
	public String getColumnText(Selenium selenium, String iTable, String iName,
			int iTd) throws Exception {
/*		String Next_LINK = "link=Next";
		String First_LINK = "link=1";*/
		
		iName=iName.trim();
		iTable=iTable.trim();

		if (selenium.isElementPresent(First_LINK)) {
			selenium.click(First_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}


		while (selenium.isElementPresent(Next_LINK)) {
			try {
				int i = 1;
				while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
					if (selenium.getText(
							iTable + "//tr[" + i + "]//td[" + 2 + "]")
							.equals(iName)) {
						return selenium.getText(iTable + "//tr[" + i
								+ "]//td[" + iTd + "]");
					}
					i++;
				}
			} catch (Exception e) {
				Reporter.log(e.toString());
				return null;
			}
			selenium.click(Next_LINK);
			selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
		}

		try {
			int i = 1;
			while (selenium.isElementPresent(iTable + "//tr[" + i + "]")) {
				if (selenium.getText(
						iTable + "//tr[" + i + "]//td[" + 2 + "]").equals(
						iName)) {
					return selenium.getText(iTable + "//tr[" + i + "]//td["
							+ iTd + "]");
				}
				i++;
			}
		} catch (Exception e) {
			Reporter.log(e.toString());
			return null;
		}
	
		return null;
	}
	
	/**
	 * This function is used for when you want to open a new page by click on locator.
	 * 
	 * It contains the waitforpagetoload() block. 
	 * 
	 * @param selenium
	 * @param locator
	 */
	public void clickAndWait(Selenium selenium, String locator) {
		selenium.click(locator);
		selenium.waitForPageToLoad( DEFAULT_WAIT_TIME );
	}
	
	/**
	 * This function is used to open a modal dialog with 'normal' way, so solving the issue that when<b>
	 * 
	 * opening an modal dialog, Selenium will hanged.
	 * 
	 * @param locator The button or link to invoke the modal dialog
	 * 
	 * @author bear
	 */
	public void clickAndOpenModalDialog( Selenium selenium, String locator ) {
		try {
			String showModalDialogCode = FileHandler.readAsString( 
					new File( JAVA_SCRIPT_DIR + "showModalDialog.js" ) );
			selenium.getEval( showModalDialogCode );
		} catch ( IOException e ) {
			Reporter.log( "Failed to read the code in showModalDialog.js." );
		}
		selenium.click( locator );
		selenium.waitForPopUp( "modal", DEFAULT_WAIT_TIME );
		selenium.selectWindow( "modal" );
	}
	
	/**
	 * This function is used to close a modal dialog and return value to its parent page
	 * 
	 * 
	 * @param locator The button or link to close the modal dialog
	 * 
	 * @param invoker The button or link in parent page to invoke the modal dialog. <b>
	 * 		  we need it to call showModalDialog for the second time and get return value
	 * 
	 * @author bear
	 */
	public void clickAndCloseModalDialog( Selenium selenium, String locator, String invoker ) {
		try {
			String closeModalDialogCode = FileHandler.readAsString( 
					new File( JAVA_SCRIPT_DIR + "closeModalDialog.js" ) );
			selenium.getEval( closeModalDialogCode );
		} catch ( IOException e ) {
			Reporter.log( "Failed to read the code in closeModalDialog.js." );
		}
		selenium.click( locator );
		selenium.selectWindow( null );
		selenium.click( invoker );
	}
	
	/**
	 * This method is designed to verify  handle the upload/download dialog 
	 * and other dialog that not comes the source code.
	 *  
	 * update 2011-8-5
	 * Author:Jack
	 */
	/*
	 *  define a handle upload function:It takes in two parameters(browser name and file path)
	 */ 
	public void handleUpload(String browser , String filepath) throws Exception{
		String execute_file = "Tools\\gs\\upload.exe";
		String cmd = "\"" + execute_file + "\"" + " " + "\"" + browser 
				   + "\""+ " " + "\"" + filepath + "\"";
		try{
			Process p=Runtime.getRuntime().exec(cmd);
			p.waitFor(); //wait fir the upload.exe to complete
		}catch(Exception e){
			e.printStackTrace();
		}
		
 	}
	/*
	 *  define a handle download function
	 */
	public void handleDownload(String browser) throws Exception{
	String execute_file = "Tools\\gs\\download.exe";
	String cmd = "\""  + execute_file + "\""  + " " + "\"" + browser + "\"";  //with arguments
	try{
		Process p=Runtime.getRuntime().exec(cmd);
		p.waitFor(); 
	   }catch(Exception e){
		e.printStackTrace();
	   }
	}
	
	/**
	 * Wait for a page element to appear, or the time is out
	 * 
	 * @param timeout time out in milliseconds
	 * 
	 * @author bear
	 */
	public void waitForElementAppear( Selenium selenium, String element, String timeout ) throws Exception {
		selenium.waitForCondition( "selenium.isElementPresent( \"" + element + "\" );", timeout );
	}
}
